#ifndef __WIZ_DATATYPE_MULTIMAP_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_MULTIMAP_HPP__SHANHAOBO_19800429__

#include <map>

#include "../../Base/WizBase.hpp"
#include "./WizDataTypeForEach.hpp"

#define WIZ_DECLARE_MULTIMAP(i, v)                          \
    namespace MultiMap                                      \
    {                                                       \
    typedef ::Wiz::MultiMap::Type<i, v>  Type;              \
    WIZ_DECLARE(Type);                                      \
    typedef Type::tIterator         tIterator;              \
    typedef Type::tIteratorConst    tIteratorConst;         \
    typedef Type::tForEach          tForEach;               \
    typedef Type::tForEachConst     tForEachConst;          \
    typedef Type::tForEachIter      tForEachIter;           \
    }

namespace Wiz
{
    namespace MultiMap
    {
        template<class IndexT, class ValueT, class CompT = ::std::less<IndexT>>
        struct Type : private ::std::multimap<IndexT, ValueT, CompT>
        {
            //////////////////////////////////////////////////////////////////////////
            typedef IndexT                                          tIndex;
            typedef const tIndex                                    tIndexConst;
            WIZ_DECLARE_IO_WITHNAME(tIndex, tIndex);
            WIZ_DECLARE_REF_WITHNAME(tIndex, tIndex);

            typedef ValueT                                          tValue;
            typedef const tValue                                    tValueConst;
            WIZ_DECLARE_IO_WITHNAME(tValue, tValue);
            WIZ_DECLARE_REF_WITHNAME(tValue, tValue);

            typedef CompT                                           tComp;
            WIZ_DECLARE_IO_WITHNAME(tComp, tComp);

            typedef ::std::multimap<tIndex, tValue, CompT>          tSuper;
            WIZ_DECLARE_IO_WITHNAME(tSuper, tSuper);

            typedef ::Wiz::MultiMap::Type<tIndex, tValue, CompT>    tThis;

            typedef typename tSuper::iterator                       tSuperIterator;
            typedef typename tSuper::const_iterator                 tSuperIteratorConst;
            ////////////////////////////////////////////////////////////////////////

            ////////////////////////////////////////////////////////////////////////
            typedef ::Wiz::ForEach::Type<tThis>                     tForEach;
            typedef ::Wiz::ConstForEach::Type<tThis>                tForEachConst;
            typedef ::Wiz::MapForEachIter::Type<tThis>              tForEachIter;
            //////////////////////////////////////////////////////////////////////////
            struct tIterator : public tSuperIterator
            {
                tIterator()
                {

                }
                tIterator(tSuperIterator Itr) : tSuperIterator(Itr)
                {

                }
                tIndexRefConst GetIndex() const
                {
                    return (*this)->first;
                }

                tValueRef GetValue() const
                {
                    return (*this)->second;
                }
            };
            struct tIteratorConst : public tSuperIteratorConst
            {
                tIteratorConst()
                {

                }
                tIteratorConst(tSuperIteratorConst itr) : tSuperIteratorConst(itr)
                {

                }
                tIndexRefConst GetIndex() const
                {
                    return (*this)->first;
                }

                tValueRefConst GetValue() const
                {
                    return (*this)->second;
                }
            };
            //////////////////////////////////////////////////////////////////////////
		public:
			Type() : tSuper(){}
			Type(const tSuper& InSuper) : tSuper(InSuper){}
		public:
            //////////////////////////////////////////////////////////////////////////
            tIterator Begin()
            {
                return tSuper::begin();
            }

            tIteratorConst Begin() const
            {
                return tSuper::begin();
            }

            tIterator End()
            {
                return tSuper::end();
            }

            tIteratorConst End() const
            {
                return tSuper::end();
            }

            ///-----------------------///

            ::Wiz::Size::Type Size() const
            {
                return ::Wiz::Cast::Static<::Wiz::Size::Type>(tSuper::size());
            }

            ::Wiz::Void::Type Clear()
            {
                tSuper::clear();
            }

            tIterator Erase(tIterator itr)
            {
                return tSuper::erase(itr);
            }

            ///-----------------------///

            template<class FuncT>
            ::Wiz::Void::Type FindIf(FuncT Func)
            {
                ::std::find_if(tSuper::begin(), tSuper::end(), Func);
            }

            template<class FuncT>
            ::Wiz::Void::Type RemoveIf(FuncT Func)
            {
                tSuper::iterator newend = ::std::remove_if(tSuper::begin(), tSuper::end(), Func);
                tSuper::erase(newend, tSuper::end());
            }

            ///-----------------------///

            ::Wiz::Size::Type CountBound(tIndexIn v)
            {
                return tSuper::count(v);
            }

            tIterator LowerBound(tIndexIn v)
            {
                return tSuper::lower_bound(v);
            }

            tIterator UpperBound(tIndexIn v)
            {
                return tSuper::upper_bound(v);
            }


            ///-----------------------///

            ::Wiz::Bool::Type HasData(tIndexIn v) const
            {
                return tSuper::count(v) != 0;
            }


            ///-----------------------///

            tIterator Insert(tIndex f, tValue s)
            {
                return tSuper::insert(tSuper::value_type(f, s));
            }

            ////////////////////////////////////////////////////////////////////////

            ::Wiz::Void::Type Merge(tThis Temp)
            {
                tForEachIter    FE(Temp);

                while (FE)
                {
                    Insert(FE->GetIndex(), FE->GetValue());
                    FE++;
                }
            }

            ////////////////////////////////////////////////////////////////////////
            struct ForEachBound
            {
                ::Wiz::UInt::Type m_Count, m_Curr;
                tIterator m_Next;
                ForEachBound(::Wiz::MultiMap::Type<tIndex, tValue, CompT>& mm, tIndexIn v)
                {
                    m_Next  = mm.LowerBound(v);
                    m_Count = mm.CountBound(v);
                    m_Curr  = 0;
                }

                ::Wiz::Bool::Type operator()(tIterator& Curr)
                {
                    Curr = m_Next;
                    if (m_Curr < m_Count)
                    {
                        m_Next++;
                        m_Curr++;
                        return ::Wiz::Bool::True;
                    }
                    return ::Wiz::Bool::False;
                }

                ::Wiz::Void::Type Erase(::Wiz::MultiMap::Type<tIndex, tValue, CompT>& a, tIterator Curr)
                {
                    m_Next = a.Erase(Curr);
                }
            };
            //////////////////////////////////////////////////////////////////////////
        }; /// end of struct Type
    } /// end of namespace MultiMap
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_MULTIMAP_HPP__SHANHAOBO_19800429__*/
